#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

#define MULTICAST_GROUP "224.0.0.1"
#define PORT 8888
#define BLOCK_SIZE 1400

struct FileHeader {
    uint32_t fileSize;
    char filename[256];
};

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
        return 1;
    }

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("socket");
        return 1;
    }

    int ttl = 1;
    if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
        perror("setsockopt TTL");
        close(sock);
        return 1;
    }

    struct sockaddr_in multicastAddr;
    memset(&multicastAddr, 0, sizeof(multicastAddr));
    multicastAddr.sin_family = AF_INET;
    multicastAddr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP);
    multicastAddr.sin_port = htons(PORT);

    std::ifstream file(argv[1], std::ios::binary | std::ios::ate);
    if (!file) {
        perror("open file");
        close(sock);
        return 1;
    }

    std::streampos fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    FileHeader header;
    strncpy(header.filename, argv[1], sizeof(header.filename) - 1);
    header.filename[sizeof(header.filename) - 1] = '\0';
    header.fileSize = htonl(static_cast<uint32_t>(fileSize));

    if (sendto(sock, &header, sizeof(header), 0, (struct sockaddr*)&multicastAddr, sizeof(multicastAddr)) != sizeof(header)) {
        perror("send header");
        close(sock);
        file.close();
        return 1;
    }

    char buffer[BLOCK_SIZE];
    while (!file.eof()) {
        file.read(buffer, BLOCK_SIZE);
        ssize_t bytesRead = file.gcount();
        if (sendto(sock, buffer, bytesRead, 0, (struct sockaddr*)&multicastAddr, sizeof(multicastAddr)) != bytesRead) {
            perror("send data");
            break;
        }
    }

    file.close();
    close(sock);
    return 0;
}